#include "VLDST.h"

void VLDST_0::Execute(instruction* vldst_instr) {
    addr_size_t temp_addr = 0;
    switch(vldst_instr->get_opcode()){
        case VLDDWDM2:
            if (vldst_instr->get_ldst_mode() <= 5) { 
            //AR[ucst10]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                    static_cast<immediate_operand*>(vldst_instr->get_operands(1))->get_imme_value(),
                                                        vldst_instr->get_ldst_mode(), DW);
            } else {
            //AR[OR]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                    static_cast<register_operand*>(vldst_instr->get_operands(1))->get_reg_id(),
                                                        vldst_instr->get_ldst_mode(), DW);
            }
            this->do_VLDDW0M2(temp_addr, static_cast<register_operand*>(vldst_instr->get_operands(2))->get_reg_id());
        case VLDDWDM4:
            if (vldst_instr->get_ldst_mode() <= 5) { 
            //AR[ucst10]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                    static_cast<immediate_operand*>(vldst_instr->get_operands(1))->get_imme_value(),
                                                        vldst_instr->get_ldst_mode(), DW);
            } else {
            //AR[OR]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                    static_cast<register_operand*>(vldst_instr->get_operands(1))->get_reg_id(),
                                                        vldst_instr->get_ldst_mode(), DW);
            }
            this->do_VLDDW0M4(temp_addr, static_cast<register_operand*>(vldst_instr->get_operands(2))->get_reg_id());
        case VSTDWDM16:
            if (vldst_instr->get_ldst_mode() <= 5) { 
            //AR[ucst10]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                    static_cast<immediate_operand*>(vldst_instr->get_operands(1))->get_imme_value(),
                                                        vldst_instr->get_ldst_mode(), DW);
            } else {
            //AR[OR]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                    static_cast<register_operand*>(vldst_instr->get_operands(1))->get_reg_id(),
                                                        vldst_instr->get_ldst_mode(), DW);
            }
            this->do_VSTDW0M16(temp_addr, static_cast<register_operand*>(vldst_instr->get_operands(2))->get_reg_id());
        case VSTDWDM32:
            if (vldst_instr->get_ldst_mode() <= 5) { 
            //AR[ucst10]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                    static_cast<immediate_operand*>(vldst_instr->get_operands(1))->get_imme_value(),
                                                        vldst_instr->get_ldst_mode(), DW);
            } else {
            //AR[OR]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                    static_cast<register_operand*>(vldst_instr->get_operands(1))->get_reg_id(),
                                                        vldst_instr->get_ldst_mode(), DW);
            }
            this->do_VSTDW0M32(temp_addr, static_cast<register_operand*>(vldst_instr->get_operands(2))->get_reg_id());
    }
}

inline uint64_t VLDST_0::read_Reg(int reg_id) {
    return this->RF->get_register_value(reg_id);
}

inline std::vector<uint64_t>* VLDST_0::read_Vec_Reg(int reg_id) {
    return this->RF->get_vec_register_value(reg_id);
}

//因为VPU里访存的最小粒度为半字，因此判断地址是否字对齐，只需要判断半字地址是否是偶数即可
inline bool addr_aligned(uint64_t addr) {
    if (addr % 2 != 0) {
        return false;
    } else {
        return true;
    }
}

addr_size_t VLDST_0::calculate_mem_addr(int AR_reg_id, int OR_reg_id, int op, int size) {
    //AR寄存器存的是字节，AM的访问粒度为字。需要首先对AR寄存器+偏移后的地址按字对齐，再按粒度访问
    uint64_t AR_value = read_Reg(AR_reg_id);

    uint64_t OR_value = read_Reg(OR_reg_id);

    //负责后6个op，即偏移由OR寄存器提供
    switch (op) {
        case AR_ADD_OR_CONSTANT : 
            if (size == HW) {
                //将AR寄存器的字节地址转换为半字地址
                AR_value = AR_value / 4;
                //加上偏移
                AR_value += OR_value;
                if (!addr_aligned(AR_value)) {
                    //若地址不对齐，则向下取整，按字对齐
                    AR_value -= 1;
                }
                //按字节返回访存地址
                return AR_value * 4;
            } else if (size == W) {
                AR_value = AR_value / 8;
                AR_value += OR_value;
                return AR_value * 8;
            } else if (size == DW) {
                AR_value = AR_value / 16;
                AR_value += OR_value;
                return AR_value * 16;
            } else {
                std::cout << "ERROR : WRONG MEM ACCESS SIZE" << std::endl;
            }
            break;
        case AR_SUB_OR_CONSTANT : 
            if (size == HW) {
                //将AR寄存器的字节地址转换为半字地址
                AR_value = AR_value / 4;
                //加上偏移
                AR_value -= OR_value;
                if (!addr_aligned(AR_value)) {
                    //若地址不对齐，则向下取整，按字对齐
                    AR_value -= 1;
                }
                //按字节返回访存地址
                return AR_value * 4;
            } else if (size == W) {
                AR_value = AR_value / 8;
                AR_value -= OR_value;
                return AR_value * 8;
            } else if (size == DW) {
                AR_value = AR_value / 16;
                AR_value -= OR_value;
                return AR_value * 16;
            } else {
                std::cout << "ERROR : WRONG MEM ACCESS SIZE" << std::endl;
            }
            break;
        case AR_ADD_OR_VAR : 
            if (size == HW) {
                //将AR寄存器的字节地址转换为半字地址
                AR_value = AR_value / 4;
                //加上偏移
                AR_value += OR_value;
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value * 4, 1);
                if (!addr_aligned(AR_value)) {
                    //若地址不对齐，则向下取整，按字对齐
                    AR_value -= 1;
                }
                //按字节返回访存地址
                return AR_value * 4;
            } else if (size == W) {
                AR_value = AR_value / 8;
                AR_value += OR_value;
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value * 8, 1);
                return AR_value * 8;
            } else if (size == DW) {
                AR_value = AR_value / 16;
                AR_value += OR_value;
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value * 16, 1);
                return AR_value * 16;
            } else {
                std::cout << "ERROR : WRONG MEM ACCESS SIZE" << std::endl;
            }
            break;
        case AR_SUB_OR_VAR : 
            if (size == HW) {
                //将AR寄存器的字节地址转换为半字地址
                AR_value = AR_value / 4;
                //加上偏移
                AR_value -= OR_value;
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value * 4, 1);
                if (!addr_aligned(AR_value)) {
                    //若地址不对齐，则向下取整，按字对齐
                    AR_value -= 1;
                }
                //按字节返回访存地址
                return AR_value * 4;
            } else if (size == W) {
                AR_value = AR_value / 8;
                AR_value -= OR_value;
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value * 8, 1);
                return AR_value * 8;
            } else if (size == DW) {
                AR_value = AR_value / 16;
                AR_value -= OR_value;
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value * 16, 1);
                return AR_value * 16;
            } else {
                std::cout << "ERROR : WRONG MEM ACCESS SIZE" << std::endl;
            }
            break;
        case AR_VAR_ADD_OR : 
            if (size == HW) {
                //将AR寄存器的字节地址转换为半字地址
                AR_value = AR_value / 4;
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, (AR_value + OR_value)* 4, 1);
                if (!addr_aligned(AR_value)) {
                    //若地址不对齐，则向下取整，按字对齐
                    AR_value -= 1;
                }
                //按字节返回访存地址
                return AR_value * 4;
            } else if (size == W) {
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value + OR_value * 8, 1);
                return AR_value;
            } else if (size == DW) {
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value + OR_value * 16, 1);
                return AR_value;
            } else {
                std::cout << "ERROR : WRONG MEM ACCESS SIZE" << std::endl;
            }
            break;
        case AR_VAR_SUB_OR : 
            if (size == HW) {
                //将AR寄存器的字节地址转换为半字地址
                AR_value = AR_value / 4;
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, (AR_value - OR_value)* 4, 1);
                if (!addr_aligned(AR_value)) {
                    //若地址不对齐，则向下取整，按字对齐
                    AR_value -= 1;
                }
                //按字节返回访存地址
                return AR_value * 4;
            } else if (size == W) {
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value - OR_value * 8, 1);
                return AR_value;
            } else if (size == DW) {
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value - OR_value * 16, 1);
                return AR_value;
            } else {
                std::cout << "ERROR : WRONG MEM ACCESS SIZE" << std::endl;
            }
            break;
    }
}

addr_size_t VLDST_0::calculate_mem_addr(int AR_reg_id, uint64_t imm, int op, int size) {
    //AR寄存器存的是字节，AM的访问粒度为字。需要首先对AR寄存器+偏移后的地址按字对齐，再按粒度访问
    uint64_t AR_value = read_Reg(AR_reg_id);
    //负责后6个op，即偏移由OR寄存器提供
    switch (op) {
        case AR_ADD_CONSTANT : 
            if (size == HW) {
                //将AR寄存器的字节地址转换为半字地址
                AR_value = AR_value / 4;
                //加上偏移
                AR_value += imm;
                if (!addr_aligned(AR_value)) {
                    //若地址不对齐，则向下取整，按字对齐
                    AR_value -= 1;
                }
                //按字节返回访存地址
                return AR_value * 4;
            } else if (size == W) {
                AR_value = AR_value / 8;
                AR_value += imm;
                return AR_value * 8;
            } else if (size == DW) {
                AR_value = AR_value / 16;
                AR_value += imm;
                return AR_value * 16;
            } else {
                std::cout << "ERROR : WRONG MEM ACCESS SIZE" << std::endl;
            }
            break;
        case AR_SUB_CONSTANT : 
            if (size == HW) {
                //将AR寄存器的字节地址转换为半字地址
                AR_value = AR_value / 4;
                //加上偏移
                AR_value -= imm;
                if (!addr_aligned(AR_value)) {
                    //若地址不对齐，则向下取整，按字对齐
                    AR_value -= 1;
                }
                //按字节返回访存地址
                return AR_value * 4;
            } else if (size == W) {
                AR_value = AR_value / 8;
                AR_value -= imm;
                return AR_value * 8;
            } else if (size == DW) {
                AR_value = AR_value / 16;
                AR_value -= imm;
                return AR_value * 16;
            } else {
                std::cout << "ERROR : WRONG MEM ACCESS SIZE" << std::endl;
            }
            break;
        case AR_ADD_VAR : 
            if (size == HW) {
                //将AR寄存器的字节地址转换为半字地址
                AR_value = AR_value / 4;
                //加上偏移
                AR_value += imm;
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value * 4, 1);
                if (!addr_aligned(AR_value)) {
                    //若地址不对齐，则向下取整，按字对齐
                    AR_value -= 1;
                }
                //按字节返回访存地址
                return AR_value * 4;
            } else if (size == W) {
                AR_value = AR_value / 8;
                AR_value += imm;
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value * 8, 1);
                return AR_value * 8;
            } else if (size == DW) {
                AR_value = AR_value / 16;
                AR_value += imm;
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value * 16, 1);
                return AR_value * 16;
            } else {
                std::cout << "ERROR : WRONG MEM ACCESS SIZE" << std::endl;
            }
            break;
        case AR_SUB_VAR : 
            if (size == HW) {
                //将AR寄存器的字节地址转换为半字地址
                AR_value = AR_value / 4;
                //加上偏移
                AR_value -= imm;
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value * 4, 1);
                if (!addr_aligned(AR_value)) {
                    //若地址不对齐，则向下取整，按字对齐
                    AR_value -= 1;
                }
                //按字节返回访存地址
                return AR_value * 4;
            } else if (size == W) {
                AR_value = AR_value / 8;
                AR_value -= imm;
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value * 8, 1);
                return AR_value * 8;
            } else if (size == DW) {
                AR_value = AR_value / 16;
                AR_value -= imm;
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value * 16, 1);
                return AR_value * 16;
            } else {
                std::cout << "ERROR : WRONG MEM ACCESS SIZE" << std::endl;
            }
            break;
        case AR_VAR_ADD : 
            if (size == HW) {
                //将AR寄存器的字节地址转换为半字地址
                AR_value = AR_value / 4;
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, (AR_value + imm)* 4, 1);
                if (!addr_aligned(AR_value)) {
                    //若地址不对齐，则向下取整，按字对齐
                    AR_value -= 1;
                }
                //按字节返回访存地址
                return AR_value * 4;
            } else if (size == W) {
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value + imm * 8, 1);
                return AR_value;
            } else if (size == DW) {
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value + imm * 16, 1);
                return AR_value;
            } else {
                std::cout << "ERROR : WRONG MEM ACCESS SIZE" << std::endl;
            }
            break;
        case AR_VAR_SUB_OR : 
            if (size == HW) {
                //将AR寄存器的字节地址转换为半字地址
                AR_value = AR_value / 4;
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, (AR_value - imm)* 4, 1);
                if (!addr_aligned(AR_value)) {
                    //若地址不对齐，则向下取整，按字对齐
                    AR_value -= 1;
                }
                //按字节返回访存地址
                return AR_value * 4;
            } else if (size == W) {
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value - imm * 8, 1);
                return AR_value;
            } else if (size == DW) {
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value - imm * 16, 1);
                return AR_value;
            } else {
                std::cout << "ERROR : WRONG MEM ACCESS SIZE" << std::endl;
            }
            break;
    }
}

//VPU里的load类指令延迟均为9个周期
void VLDST_1::do_VLDH(addr_size_t addr, int dst_reg_id) {
    //9个周期后，将从AM加载的数据写入目标寄存器
    this->WCM->post_write_req(dst_reg_id, this->AM->load_hw_vector(addr), 9);
}

void VLDST_1::do_VLDHU(addr_size_t addr, int dst_reg_id) {
    this->WCM->post_write_req(dst_reg_id, this->AM->load_hwu_vector(addr), 9);
}

//VPU里的store类指令延迟均为4个周期
void VLDST_1::do_VSTH(addr_size_t addr, int src_reg_id) {
    //4个周期后，将源寄存器的数据存入AM相应地址
    this->WCM->post_write_req(addr, this->RF->get_vec_register_value(src_reg_id), HW, 4);
}

void VLDST_1::do_VLDW(addr_size_t addr, int dst_reg_id) {
    this->WCM->post_write_req(dst_reg_id, this->AM->load_w_vector(addr), 9);
}

void VLDST_1::do_VSTW(addr_size_t addr, int src_reg_id) {
    this->WCM->post_write_req(addr, this->RF->get_vec_register_value(src_reg_id), W, 4);
}

//!!确定指令解析时得到的dst reg id为奇数
//SLDST中dst reg为偶数，VLDST中dst reg暂且认为与SLDST相同，为了兼容性，VLDST中dst reg也为偶数
void VLDST_1::do_VLDDW(addr_size_t addr, int dst_reg_id) {
    this->do_VLDW(addr, dst_reg_id);
    //前16个字加载给偶数寄存器，地址需要+128个字节（64*16/8），从这一段开始的数据加载给奇数寄存器
    this->do_VLDW(addr + 128, dst_reg_id + 1);
}

void VLDST_1::do_VSTDW(addr_size_t addr, int src_reg_id) {
    this->do_VSTW(addr, src_reg_id);
    this->do_VSTW(addr + 128, src_reg_id + 1);
}

void VLDST_1::do_VLDDWM2(addr_size_t addr, int dst_reg_id) {
    std::vector<uint64_t>* value1 = this->AM->load_w_vector(addr);
    std::vector<uint64_t>* value2 = this->AM->load_w_vector(addr + 128);
    std::vector<uint64_t>* new_1 = new std::vector<uint64_t>();
    new_1->reserve(16);
    std::vector<uint64_t>* new_2 = new std::vector<uint64_t>();
    new_2->reserve(16);
    for (int i = 0; i < 16; i++) {
        if (i % 2 == 0) {
            new_1->push_back(value1->at(i));
        } else {
            new_2->push_back(value1->at(i));
        }
    }
    for (int i = 0; i < 16; i++) {
        if (i % 2 == 0) {
            new_1->push_back(value2->at(i));
        } else {
            new_2->push_back(value2->at(i));
        }
    }
    //旧的值不再需要，直接释放内存
    delete value1;
    delete value2;
    this->WCM->post_write_req(dst_reg_id, new_1, 9);
    this->WCM->post_write_req(dst_reg_id + 1, new_2, 9);
}

void VLDST_1::do_VSTDWM16(addr_size_t addr, int src_reg_id) {
    std::vector<uint64_t>* value1 = this->RF->get_vec_register_value(src_reg_id);
    std::vector<uint64_t>* value2 = this->RF->get_vec_register_value(src_reg_id + 1);
    std::vector<uint64_t>* new_1 = new std::vector<uint64_t>();
    new_1->reserve(16);
    std::vector<uint64_t>* new_2 = new std::vector<uint64_t>();
    new_2->reserve(16);
    for (int i = 0; i < 8; i++) {
        new_1->push_back(value1->at(i));
        new_1->push_back(value2->at(i));
    }
    for (int i = 0; i < 8; i++) {
        new_2->push_back(value1->at(i));
        new_2->push_back(value2->at(i));
    }
    //旧的值不再需要，直接释放内存
    delete value1;
    delete value2;
    this->WCM->post_write_req(addr, new_1, 4);
    this->WCM->post_write_req(addr + 128, new_2, 4);
}

void VLDST_1::do_VLDDW1M2(addr_size_t addr, int dst_reg_id) {
    this->WCM->post_write_req_m(dst_reg_id, this->AM->load_w_vector(addr), this->AM->load_w_vector(addr + 128), 2, false, 9);
}

void VLDST_1::do_VLDDW1M4(addr_size_t addr, int dst_reg_id) {
    this->WCM->post_write_req_m(dst_reg_id, this->AM->load_w_vector(addr), this->AM->load_w_vector(addr + 128), 4, false, 9);
}

void VLDST_1::do_VSTDW1M16(addr_size_t addr, int src_reg_id) {
    this->WCM->post_write_req_m(addr, this->RF->get_vec_register_value(src_reg_id), this->RF->get_vec_register_value(src_reg_id + 1), 16, false, 4);
}

void VLDST_1::do_VSTDW1M32(addr_size_t addr, int src_reg_id) {
    this->WCM->post_write_req_m(addr, this->RF->get_vec_register_value(src_reg_id), this->RF->get_vec_register_value(src_reg_id + 1), 32, false, 4);
}

void VLDST_0::do_VLDDW0M2(addr_size_t addr, int dst_reg_id) {
    this->WCM->post_write_req_m(dst_reg_id, this->AM->load_w_vector(addr), this->AM->load_w_vector(addr + 128), 2, true, 9);
}

void VLDST_0::do_VLDDW0M4(addr_size_t addr, int dst_reg_id) {
    this->WCM->post_write_req_m(dst_reg_id, this->AM->load_w_vector(addr), this->AM->load_w_vector(addr + 128), 4, true, 9);
}

void VLDST_0::do_VSTDW0M16(addr_size_t addr, int src_reg_id) {
    this->WCM->post_write_req_m(addr, this->RF->get_vec_register_value(src_reg_id), this->RF->get_vec_register_value(src_reg_id + 1), 16, true, 4);
}

void VLDST_0::do_VSTDW0M32(addr_size_t addr, int src_reg_id) {
    this->WCM->post_write_req_m(addr, this->RF->get_vec_register_value(src_reg_id), this->RF->get_vec_register_value(src_reg_id + 1), 32, true, 4);
}

void VLDST_1::Execute(instruction* vldst_instr) {

    addr_size_t temp_addr = 0;
    switch (vldst_instr->get_opcode()) {
        case VLDH:
            if (vldst_instr->get_ldst_mode() <= 5) { 
                //AR[ucst10]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<immediate_operand*>(vldst_instr->get_operands(1))->get_imme_value(),
                                                            vldst_instr->get_ldst_mode(), HW);
            } else {
                //AR[OR]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<register_operand*>(vldst_instr->get_operands(1))->get_reg_id(),
                                                            vldst_instr->get_ldst_mode(), HW);
            }
            this->do_VLDH(temp_addr, static_cast<register_operand*>(vldst_instr->get_operands(2))->get_reg_id());
        case VLDHU:
            if (vldst_instr->get_ldst_mode() <= 5) { 
                //AR[ucst10]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<immediate_operand*>(vldst_instr->get_operands(1))->get_imme_value(),
                                                            vldst_instr->get_ldst_mode(), HW);
            } else {
                //AR[OR]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<register_operand*>(vldst_instr->get_operands(1))->get_reg_id(),
                                                            vldst_instr->get_ldst_mode(), HW);
            }
            this->do_VLDHU(temp_addr, static_cast<register_operand*>(vldst_instr->get_operands(2))->get_reg_id());
        case VLDW:
            if (vldst_instr->get_ldst_mode() <= 5) { 
                //AR[ucst10]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<immediate_operand*>(vldst_instr->get_operands(1))->get_imme_value(),
                                                            vldst_instr->get_ldst_mode(), W);
            } else {
                //AR[OR]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<register_operand*>(vldst_instr->get_operands(1))->get_reg_id(),
                                                            vldst_instr->get_ldst_mode(), W);
            }
            this->do_VLDW(temp_addr, static_cast<register_operand*>(vldst_instr->get_operands(2))->get_reg_id());
        case VLDDW:
            if (vldst_instr->get_ldst_mode() <= 5) { 
                //AR[ucst10]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<immediate_operand*>(vldst_instr->get_operands(1))->get_imme_value(),
                                                            vldst_instr->get_ldst_mode(), DW);
            } else {
                //AR[OR]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<register_operand*>(vldst_instr->get_operands(1))->get_reg_id(),
                                                            vldst_instr->get_ldst_mode(), DW);
            }
            this->do_VLDDW(temp_addr, static_cast<register_operand*>(vldst_instr->get_operands(2))->get_reg_id()); 
        case VLDDWDM2:
            if (vldst_instr->get_ldst_mode() <= 5) { 
                //AR[ucst10]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<immediate_operand*>(vldst_instr->get_operands(1))->get_imme_value(),
                                                            vldst_instr->get_ldst_mode(), DW);
            } else {
                //AR[OR]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<register_operand*>(vldst_instr->get_operands(1))->get_reg_id(),
                                                            vldst_instr->get_ldst_mode(), DW);
            }
            this->do_VLDDW1M2(temp_addr, static_cast<register_operand*>(vldst_instr->get_operands(2))->get_reg_id());   
        case VLDDWM2:
            if (vldst_instr->get_ldst_mode() <= 5) { 
                //AR[ucst10]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<immediate_operand*>(vldst_instr->get_operands(1))->get_imme_value(),
                                                            vldst_instr->get_ldst_mode(), DW);
            } else {
                //AR[OR]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<register_operand*>(vldst_instr->get_operands(1))->get_reg_id(),
                                                            vldst_instr->get_ldst_mode(), DW);
            }
            this->do_VLDDWM2(temp_addr, static_cast<register_operand*>(vldst_instr->get_operands(2))->get_reg_id());   
        case VLDDWDM4:
            if (vldst_instr->get_ldst_mode() <= 5) { 
                //AR[ucst10]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<immediate_operand*>(vldst_instr->get_operands(1))->get_imme_value(),
                                                            vldst_instr->get_ldst_mode(), DW);
            } else {
                //AR[OR]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<register_operand*>(vldst_instr->get_operands(1))->get_reg_id(),
                                                            vldst_instr->get_ldst_mode(), DW);
            }
            this->do_VLDDW1M4(temp_addr, static_cast<register_operand*>(vldst_instr->get_operands(2))->get_reg_id());   
            case VSTH:
            if (vldst_instr->get_ldst_mode() <= 5) { 
                //AR[ucst10]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<immediate_operand*>(vldst_instr->get_operands(1))->get_imme_value(),
                                                            vldst_instr->get_ldst_mode(), HW);
            } else {
                //AR[OR]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<register_operand*>(vldst_instr->get_operands(1))->get_reg_id(),
                                                            vldst_instr->get_ldst_mode(), HW);
            }
            this->do_VSTH(temp_addr, static_cast<register_operand*>(vldst_instr->get_operands(2))->get_reg_id());
        case VSTW:
            if (vldst_instr->get_ldst_mode() <= 5) { 
                //AR[ucst10]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<immediate_operand*>(vldst_instr->get_operands(1))->get_imme_value(),
                                                            vldst_instr->get_ldst_mode(), W);
            } else {
                //AR[OR]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<register_operand*>(vldst_instr->get_operands(1))->get_reg_id(),
                                                            vldst_instr->get_ldst_mode(), W);
            }
            this->do_VLDW(temp_addr, static_cast<register_operand*>(vldst_instr->get_operands(2))->get_reg_id());
        case VSTDW:
            if (vldst_instr->get_ldst_mode() <= 5) { 
                //AR[ucst10]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<immediate_operand*>(vldst_instr->get_operands(1))->get_imme_value(),
                                                            vldst_instr->get_ldst_mode(), DW);
            } else {
                //AR[OR]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<register_operand*>(vldst_instr->get_operands(1))->get_reg_id(),
                                                            vldst_instr->get_ldst_mode(), DW);
            }
            this->do_VLDDW(temp_addr, static_cast<register_operand*>(vldst_instr->get_operands(2))->get_reg_id()); 
        case VSTDWDM16:
            if (vldst_instr->get_ldst_mode() <= 5) { 
                //AR[ucst10]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<immediate_operand*>(vldst_instr->get_operands(1))->get_imme_value(),
                                                            vldst_instr->get_ldst_mode(), DW);
            } else {
                //AR[OR]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<register_operand*>(vldst_instr->get_operands(1))->get_reg_id(),
                                                            vldst_instr->get_ldst_mode(), DW);
            }
            this->do_VSTDW1M16(temp_addr, static_cast<register_operand*>(vldst_instr->get_operands(2))->get_reg_id());   
        case VSTDWM16:
            if (vldst_instr->get_ldst_mode() <= 5) { 
                //AR[ucst10]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<immediate_operand*>(vldst_instr->get_operands(1))->get_imme_value(),
                                                            vldst_instr->get_ldst_mode(), DW);
            } else {
                //AR[OR]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<register_operand*>(vldst_instr->get_operands(1))->get_reg_id(),
                                                            vldst_instr->get_ldst_mode(), DW);
            }
            this->do_VSTDWM16(temp_addr, static_cast<register_operand*>(vldst_instr->get_operands(2))->get_reg_id());   
        case VSTDWDM32:
            if (vldst_instr->get_ldst_mode() <= 5) { 
                //AR[ucst10]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<immediate_operand*>(vldst_instr->get_operands(1))->get_imme_value(),
                                                            vldst_instr->get_ldst_mode(), DW);
            } else {
                //AR[OR]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(vldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<register_operand*>(vldst_instr->get_operands(1))->get_reg_id(),
                                                            vldst_instr->get_ldst_mode(), DW);
            }
            this->do_VSTDW1M32(temp_addr, static_cast<register_operand*>(vldst_instr->get_operands(2))->get_reg_id()); 
            
    }

}